package com.asgard.crypto;

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

public interface CryptoServiceProvider {
    /**
     * 哈希
     *
     * @param data 一组或多组原始数据
     * @return 哈希结果
     */
    byte[] hash(byte[]... data);

    /**
     * 两次哈希
     *
     * @param data 一组或多组原始数据
     * @return 哈希结果
     */
    byte[] hashTwice(byte[]... data);

    /**
     * 生成对称加密密钥
     *
     * @return 对称加密密钥
     */
    byte[] generateKey();

    /**
     * 生成对称加密密钥
     *
     * @param password 密码
     * @param salt     盐值
     * @param useKDF   是否使用 Scrypt 等 KDF 函数生成对称密钥
     * @return 对称加密密钥
     */
    byte[] generateKey(String password, byte[] salt, boolean useKDF);

    /**
     * 生成非对称加密密钥对
     *
     * @return 非对称加密密钥对
     */
    KeyPair generateKeyPair();

    /**
     * 根据私钥和原始数据生成数字签名
     *
     * @param privateKey 私钥
     * @param data       数据
     * @return 数字签名
     */
    byte[] sign(PrivateKey privateKey, byte[] data);

    /**
     * 校验签名是否正确
     *
     * @param publicKey 公钥
     * @param data      数据
     * @param signature 数字签名
     * @return 签名是否正确
     */
    boolean verify(PublicKey publicKey, byte[] data, byte[] signature);


    /**
     * 非对称加密
     *
     * @param publicKey 公钥
     * @param data      数据
     * @return 密文
     */
    byte[] asymmetricEncrypt(PublicKey publicKey, byte[] data);

    /**
     * 非对称解密
     *
     * @param privateKey 私钥
     * @param cipherText 数据
     * @return 明文
     */
    byte[] asymmetricDecrypt(PrivateKey privateKey, byte[] cipherText);

    /**
     * 对称加密
     *
     * @param key  密钥
     * @param data 数据
     * @return 密文
     */
    byte[] symmetricEncrypt(byte[] key, byte[] data);

    /**
     * 对称解密
     *
     * @param key        私钥
     * @param cipherText 数据
     * @return 明文
     */
    byte[] symmetricDecrypt(byte[] key, byte[] cipherText);

    /**
     * 解析私钥
     *
     * @param privateKeyBytes 私钥字节数组
     * @return 私钥
     */
    PrivateKey parsePrivateKey(byte[] privateKeyBytes);

    /**
     * 解析公钥
     *
     * @param publicKeyBytes 公钥字节数组
     * @return 公钥
     */
    PublicKey parsePublicKey(byte[] publicKeyBytes);

    /**
     * 从私钥产生公钥
     *
     * @param privateKey 私钥
     * @return 公钥
     */
    PublicKey generatePublicKey(PrivateKey privateKey) throws InvalidKeySpecException;
}
